package com.lancer.cloud.common.util;

import com.alibaba.fastjson.JSONObject;
import com.lancer.cloud.common.constants.BaseConstants;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * http请求GET和 POST工具类
 *
 * @author Even Chan
 */
@Slf4j
public class HttpRequestUtils {

    /**
     * 默认连接超时时间：毫秒
     */
    private final static int DEFAULT_CONNECT_TIMEOUT = 6000;
    /**
     * 默认读取超时时间：毫秒
     */
    private final static int DEFAULT_READ_TIMEOUT = 12000;

    public final static String CONTENT_TYPE_DEF = "application/x-www-form-urlencoded";

    public final static String CONTENT_TYPE_JSON = "application/json; charset=utf-8";

    public final static String httpUrl = "http://apis.baidu.com/showapi_open_bus/mobile/find";

    /***************************************************** GET请求 *******************************************************/
    /**
     * GET请求
     */
    public static String readContentFromGet(String url) throws IOException {
        return readContentFromGet(url, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT, null);
    }

    /**
     * GET请求
     */
    public static String readContentFromGet(String url, int connectTimeout, int readTimeout)
        throws IOException {
        return readContentFromGet(url, connectTimeout, readTimeout, null);
    }

    /**
     * GET请求，UTF-8编码
     */
    public static String readContentFromGetOfUTF8(String url) throws IOException {
        return readContentFromGet(url, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT,
            BaseConstants.ENCODE_UTF8);
    }

    /**
     * GET请求，GB2312编码
     */
    public static String readContentFromGetOfUTF8(String url, int connectTimeout, int readTimeout)
        throws IOException {
        return readContentFromGet(url, connectTimeout, readTimeout, BaseConstants.ENCODE_UTF8);
    }

    /**
     * GET请求，GB2312编码
     */
    public static String readContentFromGetOfGB2312(String url) throws IOException {
        return readContentFromGet(url, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT,
            BaseConstants.ENCODE_GB2312);
    }

    /**
     * GET请求，GB2312编码
     */
    public static String readContentFromGetOfGB2312(String url, int connectTimeout, int readTimeout)
        throws
        IOException {
        return readContentFromGet(url, connectTimeout, readTimeout, BaseConstants.ENCODE_GB2312);
    }

    /**
     * GET请求
     */
    public static String readContentFromGet(String url, int connectTimeout, int readTimeout,
        String encode) throws
        IOException {
        URL getUrl = new URL(url);
        // 根据拼凑的URL,打开连接,URL.openConnection()函数会根据URL的类型，返回不同的URLConnection子类的对象,在这里我们的URL是一个http，因此它实际上返回的是HttpURLConnection
        HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
        // 建立与服务器的连接，并未发送数据
        connection.setConnectTimeout(connectTimeout);
        connection.setReadTimeout(readTimeout);
        connection.connect();
        // 发送数据到服务器并使用Reader读取返回的数据
        StringBuilder sb = new StringBuilder();
        BufferedReader in;
        if (encode == null) {
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        } else {
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), encode));
        }
        String line;
        // 读取返回的内容
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        in.close();
        // 断开连接
        connection.disconnect();
        return sb.toString();
    }

    /***************************************************** POST请求 *******************************************************/
    /**
     * POST请求
     */
    public static String readContentFromPost(String url, String content) throws IOException {
        return readContentFromPost(url, content, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT,
            null);
    }

    /**
     * POST请求
     */
    public static String readContentFromPost(String url, String content, int connectTimeout,
        int readTimeout) throws
        IOException {
        return readContentFromPost(url, content, connectTimeout, readTimeout, null);
    }

    /**
     * POST请求,编码gb2312
     */
    public static String readContentFromPostOfGB2312(String url, String content)
        throws IOException {
        return readContentFromPost(url, content, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT,
            BaseConstants.ENCODE_GB2312);
    }

    /**
     * POST请求,编码gb2312
     */
    public static String readContentFromPostOfGB2312(String url, String content, int connectTimeout,
        int readTimeout) throws
        IOException {
        return readContentFromPost(url, content, connectTimeout, readTimeout,
            BaseConstants.ENCODE_GB2312);
    }

    /**
     * POST请求,编码utf-8
     */
    public static String readContentFromPostOfUTF8(String url, String content) throws IOException {
        return readContentFromPost(url, content, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT,
            BaseConstants.ENCODE_UTF8);
    }

    /**
     * readTimeout
     */
    public static String readContentFromPostOfUTF8(String url, String content, int connectTimeout,
        int readTimeout) throws IOException {
        return readContentFromPost(url, content, connectTimeout, readTimeout,
            BaseConstants.ENCODE_UTF8);
    }

    /**
     * POST请求
     */
    public static String readContentFromPost(String url, String content, int connectTimeout, int readTimeout, String encode) throws IOException {
        // 打开连接
        HttpURLConnection connection = initConnection(new URL(url), "POST");
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded ");
        connection.setConnectTimeout(connectTimeout);
        connection.setReadTimeout(readTimeout);
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        if (StringUtils.isNotBlank(encode)) {
            out.write(content.getBytes(encode));
        } else {
            out.write(content.getBytes());
        }
        out.flush();
        out.close();
        // 发送数据到服务器并使用Reader读取返回的数据
        BufferedReader reader;
        if (StringUtils.isNotBlank(encode)) {
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        } else {
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), encode));
        }
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        // 关闭连接
        connection.disconnect();
        return sb.toString();
    }

    /***************************************************** GET请求 JSON *******************************************************/
    /**
     * POST请求，post域为json格式
     */
    public static String readContentFromPostJson(String url, String content,
        Map<String, String> headersMap) throws
        IOException {
        return readContentFromPostJson(url, content, headersMap, DEFAULT_CONNECT_TIMEOUT,
            DEFAULT_READ_TIMEOUT);
    }

    /**
     * POST请求，post域为json格式
     */
    public static String readContentFromPostJson(String url, String content,
        Map<String, String> headersMap, int connectTimeout, int readTimeout) throws IOException {
        HttpURLConnection connection = initConnection(new URL(url), "POST");
        connection.setInstanceFollowRedirects(true);
        connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
        connection.addRequestProperty("Accept-Charset", "UTF-8");
        if (headersMap != null && headersMap.size() > 0) {
            for (Map.Entry<String, String> header : headersMap.entrySet()) {
                connection.addRequestProperty(header.getKey(), header.getValue());
            }
        }
        connection.setConnectTimeout(connectTimeout);
        connection.setReadTimeout(readTimeout);
        // 此处getOutputStream会隐含的进行connect(即：调用connect()方法)。
        PrintWriter out = new PrintWriter(
            new OutputStreamWriter(connection.getOutputStream(), "utf-8"));
        out.println(content);
        out.flush();
        out.close();
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(connection.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        // 关闭连接
        connection.disconnect();
        return sb.toString();
    }

    /**
     * POST请求，post域为json格式
     */
    public static String readContentFromPostJson(String url, String content) throws IOException {
        return readContentFromPostJson(url, content, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT);
    }

    /**
     * POST请求，post域为json格式
     */
    public static String readContentFromPostJson(String url, String content, int connectTimeout,
        int readTimeout) throws
        IOException {
        URL postUrl = new URL(url);
        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setRequestMethod("POST");
        connection.setUseCaches(false);
        connection.setInstanceFollowRedirects(true);
        connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
        connection.addRequestProperty("Accept-Charset", "UTF-8");
        connection.setConnectTimeout(connectTimeout);
        connection.setReadTimeout(readTimeout);
        PrintWriter out = new PrintWriter(
            new OutputStreamWriter(connection.getOutputStream(), "utf-8"));
        out.println(content);
        out.flush();
        out.close();
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(connection.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        // 关闭连接
        connection.disconnect();
        return sb.toString();
    }

    /**
     * 从request 中获得 post数据
     */
    public static String readContentFormRequest(HttpServletRequest request) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        return sb.toString();

    }

    /**
     * 从request 中获得 post数据的json数据并做解析
     */
    public static <T> T readContentFormRequest(HttpServletRequest request, Class<T> jsonClass)
        throws IOException {
        String json = readContentFormRequest(request);
        if (StringUtils.isBlank(json)) {
            throw new IOException();
        }
        return (T) JSONObject.parseObject(json, jsonClass);
    }

    /**
     * 从request 中获得 post数据的并转换为Json
     */
    public static JSONObject readContentFormRequestToJsonObj(HttpServletRequest request)
        throws IOException {
        String json = readContentFormRequest(request);
        if (StringUtils.isBlank(json)) {
            throw new IOException();
        }
        return JSONObject.parseObject(json);
    }


    private static HttpURLConnection initConnection(URL url, String requestType)
        throws IOException {
        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 打开读写属性，默认均为false
        connection.setDoOutput(true);
        connection.setDoInput(true);
        // 设置请求方式，默认为GET
        connection.setRequestMethod("POST");
        // Post 请求不能使用缓存
        connection.setUseCaches(false);
        connection.setInstanceFollowRedirects(true);
        return connection;
    }
}
